<template>
  <div class="main-content-box">
    <div class="demoDiv">
      <div class="title_for_layout">
        <h3>切换模式增加节点或者边</h3>
      </div>
      <div class="toolDiv">
        <div class="zoom zoomOut" title="放大" @click="getZoomOut">
          <i class="iconfont">&#xe640;</i>
        </div>
        <div class="zoom zoomIn" title="缩小" @click="getZoomIn">
          <i class="iconfont">&#xe624;</i>
        </div>
        <div class="zoom showGrid" title="显示网格" @click="showGrid">
          <i class="iconfont">&#xe63a;</i>
        </div>
        <div class="zoom hideGird" title="关闭网格" @click="hideGird">
          <i class="iconfont">&#xe675;</i>
        </div>
        <div class="zoom defaultMode" title="默认模式" @click="defaultMode">
          <i class="iconfont">&#xe615;</i>
        </div>
        <div class="zoom addNode" title="添加节点" @click="addNode">
          <i class="iconfont">&#xe614;</i>
        </div>
        <div class="zoom addEdge" title="添加边" @click="addEdge">
          <i class="iconfont">&#xe641;</i>
        </div>
      </div>
      <div id="container"></div>
    </div>
  </div>
</template>

<script>
import G6 from "@antv/g6";
import Util from "@antv/g6/lib/util";

export default {
  name: "addEdgeOrNode",
  data () {
    return {
      currentGraph: {},
      currentGrid: {},
      demoData: {
        nodes: [
          {
            id: 'node1',
            x: 100,
            y: 200,
          },
          {
            id: 'node2',
            x: 300,
            y: 200,
          },
          {
            id: 'node3',
            x: 300,
            y: 300,
          },
        ],
        edges: [
          {
            id: 'edge1',
            target: 'node2',
            source: 'node1',
          },
        ],
      },
      isClickAddNode: false,
      isClickAddEdge: false,
      showGridClick: false
    };
  },
  created () {
    console.log(Util)
  },
  mounted () {
    this.initGrahp();
  },
  methods: {
    initGrahp () {
      let _that = this
      /**
       * 该案例演示切换交互模式，在不同模式下实现拖动节点、增加节点、增加边的交互行为。
       */
      let addedCount = 0;
      // Register a custom behavior: add a node when user click the blank part of canvas
      G6.registerBehavior('click-add-node', {
        // Set the events and the corresponding responsing function for this behavior
        getEvents () {
          // The event is canvas:click, the responsing function is onClick
          return {
            'canvas:click': 'onClick',
          };
        },
        // Click event
        onClick (ev) {
          const self = this;
          const graph = self.graph;
          // Add a new node
          graph.addItem('node', {
            x: ev.canvasX,
            y: ev.canvasY,
            id: `node-${addedCount}`, // Generate the unique id
          });
          addedCount++;
        },
      });
      // Register a custom behavior: click two end nodes to add an edge
      G6.registerBehavior('click-add-edge', {
        // Set the events and the corresponding responsing function for this behavior
        getEvents () {
          return {
            'node:click': 'onClick', // The event is canvas:click, the responsing function is onClick
            mousemove: 'onMousemove', // The event is mousemove, the responsing function is onMousemove
            'edge:click': 'onEdgeClick', // The event is edge:click, the responsing function is onEdgeClick
          };
        },
        // The responsing function for node:click defined in getEvents
        onClick (ev) {
          const self = this;
          const node = ev.item;
          const graph = self.graph;
          // The position where the mouse clicks
          const point = { x: ev.x, y: ev.y };
          const model = node.getModel();
          if (self.addingEdge && self.edge) {
            graph.updateItem(self.edge, {
              target: model.id,
            });

            self.edge = null;
            self.addingEdge = false;
          } else {
            // Add anew edge, the end node is the current node user clicks
            self.edge = graph.addItem('edge', {
              source: model.id,
              target: model.id,
            });
            self.addingEdge = true;
          }
        },
        // The responsing function for mousemove defined in getEvents
        onMousemove (ev) {
          const self = this;
          // The current position the mouse clicks
          const point = { x: ev.x, y: ev.y };
          if (self.addingEdge && self.edge) {
            // Update the end node to the current node the mouse clicks
            self.graph.updateItem(self.edge, {
              target: point,
            });
          }
        },
        // The responsing function for edge:click defined in getEvents
        onEdgeClick (ev) {
          const self = this;
          const currentEdge = ev.item;
          if (self.addingEdge && self.edge === currentEdge) {
            self.graph.removeItem(self.edge);
            self.edge = null;
            self.addingEdge = false;
          }
        },
      });
      // Initial data
      const data = {
        nodes: [
          {
            id: 'node1',
            x: 100,
            y: 200,
          },
          {
            id: 'node2',
            x: 300,
            y: 200,
          },
          {
            id: 'node3',
            x: 300,
            y: 300,
          },
        ],
        edges: [
          {
            id: 'edge1',
            target: 'node2',
            source: 'node1',
          },
        ],
      };
      /**
       * 此处获取容器高度的代码，提前，避免在增加了选择模式的元素后，canvas高度不能撑开容器
       * 如果设置容器的固定高度，则此处不需要提前
       */
      const width = document.getElementById("container").scrollWidth;
      console.log(width)
      const height = document.getElementById("container").scrollHeight || 600;
      console.log(height)


      // const graphContainer = document.getElementById('container');

      // Add a selector to DOM
      /* const selector = document.createElement('select');
      selector.id = 'selector';
      const selection1 = document.createElement('option');
      selection1.value = 'default';
      selection1.innerHTML = 'Default Mode';
      const selection2 = document.createElement('option');
      selection2.value = 'addNode';
      selection2.innerHTML = 'Add Node (By clicking canvas)';
      const selection3 = document.createElement('option');
      selection3.value = 'addEdge';
      selection3.innerHTML = 'Add Edge (By clicking two end nodes)';
      selector.appendChild(selection1);
      selector.appendChild(selection2);
      selector.appendChild(selection3);
      graphContainer.appendChild(selector); */

      // const grid = new G6.Grid();
      const graph = new G6.Graph({
        container: 'container',
        width,
        height,
        center: [width / 2, height / 2],
        // The sets of behavior modes
        modes: {
          // Defualt mode
          default: ['drag-node', 'click'],
          // Adding node mode
          addNode: ['click-add-node', 'click'],
          // Adding edge mode
          addEdge: ['click-add-edge', 'click'],
        },
        // The node styles in different states
        nodeStateStyles: {
          // The node styles in selected state
          selected: {
            stroke: '#666',
            lineWidth: 2,
            fill: 'steelblue'
          }
        },
        // plugins: [grid]
      });
      graph.data(_that.demoData);
      graph.render();

      _that.currentGraph = graph
      // Listen to the selector, change the mode when the selector is changed
      /* selector.addEventListener('change', e => {
        const value = e.target.value;
        // change the behavior mode
        graph.setMode(value);
      }); */
    },
    getZoomOut () {
      let currentZoom = this.currentGraph.getZoom();
      this.currentGraph.zoomTo(currentZoom + 0.1, this.getViewCenter());
    },
    getZoomIn () {
      const currentZoom = this.currentGraph.getZoom();
      this.currentGraph.zoomTo(currentZoom - 0.1, this.getViewCenter());
    },
    /**
     * 计算画布的padding值
     */
    getFormatPadding () {
      return Util.formatPadding(this.currentGraph.get("fitViewPadding"));
    },
    /**
     * 画布中心位置
     */
    getViewCenter () {
      const padding = this.getFormatPadding();
      // console.log(padding)
      const graph = this.currentGraph;
      const width = this.currentGraph.get("width");
      const height = graph.get("height");
      return {
        x: (width - padding[2] - padding[3]) / 2 + padding[3],
        y: (height - padding[0] - padding[2]) / 2 + padding[0],
      };
    },
    /**
     * 显示或隐藏画布，画布插件需要在使用时实例化
     * 防止多次点击造成加载多个grid，需要其实每次只能加载一个
     */
    showGrid () {
      if (!this.showGridClick) {
        this.currentGrid = new G6.Grid();
        this.currentGraph.addPlugin(this.currentGrid)
        this.showGridClick = true
      }
    },

    hideGird () {
      this.showGridClick = false
      this.currentGraph.removePlugin(this.currentGrid)
    },

    defaultMode () {
      /**
       * 通过setMode方法，设置图的行为模式
       */
      this.currentGraph.setMode('default')
    },

    addNode () {
      this.isClickAddNode = true
      this.currentGraph.setMode('addNode')
    },

    addEdge () {
      this.isClickAddEdge = true
      this.currentGraph.setMode('addEdge')
    }

  },
};
</script>

<style scoped>
.main-content-box {
  width: 95%;
  margin: 5px 20px;
}
.demoDiv {
  position: relative;
  padding: 20px;
  border: 1px solid skyblue;
}
.toolDiv {
  width: 50px;
  border: 1px solid #f5f5f5;
  position: absolute;
  z-index: 100;
}
.zoom {
  cursor: pointer;
  border: 1px solid #f5f5f5;
  font-size: 26px;
  background-color: #ffffff;
}
/* 右键菜单及显示详情区域 */
.showDetails {
  width: 12vw;
  height: 40vh;
  border: 1px solid #f5f5f5;
  box-shadow: -5px 5px 5px #aaaaaa;
  position: absolute;
  top: 0;
  right: 0;
  border-radius: 4px;
  background-color: #ffffff;
  padding: 5px;
  overflow-y: auto;
  font-size: 12px;
}
.details-title {
  text-align: left;
}
.closeDetail {
  position: absolute;
  right: 8px;
  top: 18px;
  cursor: pointer;
}
.closeDetail:hover {
  color: #e27e7e;
}
.details-info {
  margin: 0 10px;
  background-color: aquamarine;
}
.details-info-items {
  background-color: #ffffff;
  display: flex;
}
.details-info-items:last-child {
  background-color: #ffffff;
  display: flex;
  flex-direction: column;
  align-items: baseline;
}
.info-items {
  font-size: 12px;
  color: #545454;
  text-align: left;
}
.info-items-label {
  color: #000000;
  text-align: left;
  width: 65px;
}
.info-items-description {
  height: 100px;
  width: 100%;
  border: 1px solid #d2bebe;
  margin-top: 0px;
  line-height: 24px;
}
/* 右键菜单 */
.demoDiv >>> #contextMenu {
  position: absolute;
  list-style-type: none;
  padding: 10px 8px;
  left: -300px;
  background-color: rgba(255, 255, 255, 0.9);
  border: 1px solid #e2e2e2;
  border-radius: 4px;
  font-size: 14px;
  color: #545454;
  z-index: 2;
}
.demoDiv >>> #contextMenu li {
  cursor: pointer;
  list-style-type: none;
  list-style: none;
  margin-left: 0px;
  margin-top: 5px;
}
.demoDiv >>> #contextMenu li:hover {
  color: #aaa;
}
.title_for_layout {
  position: absolute;
  top: 0;
  left: 100px;
  color: crimson;
}
</style>